package com.rinlink.jbcodec;

import com.alibaba.fastjson.JSONObject;
import com.rinlink.jbcodec.creator.*;
import com.rinlink.jbcodec.context.ObjectToBytesCreatorContext;
import com.rinlink.jbcodec.transform.BytesToJSON;
import com.rinlink.jbcodec.transform.JSONToBytes;

import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;


public class JSONCodec implements Codec<JSONObject>  {

/*    public Map<String, ByteBufferToObjectCreator> decodes = new HashMap<>();
    public Map<String, ObjectToBytesCreator> encodes = new HashMap<>();*/

    /*private JSONToBytesCreator creator = new JSONToBytesCreator();*/
   /* private JSONToBytes jsonToBytes;
    private BytesToJSON bytesToJSON;
    private JSONToBytesCreator jsonToBytesCreator;
    private ByteBufferToObjectCreator byteBufferToObjectCreator;*/
    ObjectToBytesCreatorMap objectToBytesCreatorMap;

    BytesToObjectCreatorMap bytesToObjectCreatorMap;

    public JSONCodec(){
        objectToBytesCreatorMap = new ObjectToBytesCreatorMap();

        objectToBytesCreatorMap.add("var_string",new VariableStringToBytesCreator());
        objectToBytesCreatorMap.add("string",new StringToBytesCreator());
        objectToBytesCreatorMap.add("hex_string",new HexStringToBytesCreator());
        objectToBytesCreatorMap.add("var_hex_string",new VariableHexStringToBytesCreator());

        objectToBytesCreatorMap.add("boolean",new BooleanToBytesCreator());
        objectToBytesCreatorMap.add("boolean_array",new BooleanArrayToBytesCreator());
        objectToBytesCreatorMap.add("boolean_list",new BooleanListToBytesCreator());

        objectToBytesCreatorMap.add("byte",new ByteToBytesCreator());
        objectToBytesCreatorMap.add("byte_array",new ByteArrayToBytesCreator());
        objectToBytesCreatorMap.add("byte_list",new ByteListToBytesCreator());

        objectToBytesCreatorMap.add("short",new ShortToBytesCreator());
        objectToBytesCreatorMap.add("short_array",new ShortArrayToBytesCreator());
        objectToBytesCreatorMap.add("short_list",new ShortListToBytesCreator());

        objectToBytesCreatorMap.add("float",new FloatToBytesCreator());
        objectToBytesCreatorMap.add("float_array",new FloatArrayToBytesCreator());
        objectToBytesCreatorMap.add("float_list",new FloatListToBytesCreator());

        objectToBytesCreatorMap.add("int",new IntegerToBytesCreator());
        objectToBytesCreatorMap.add("int_array",new IntegerArrayToBytesCreator());
        objectToBytesCreatorMap.add("int_list",new IntegerListToBytesCreator());

        objectToBytesCreatorMap.add("long",new LongToBytesCreator());
        objectToBytesCreatorMap.add("long_array",new LongArrayToBytesCreator());
        objectToBytesCreatorMap.add("long_list",new LongListToBytesCreator());


        objectToBytesCreatorMap.add("double",new DoubleToBytesCreator());
        objectToBytesCreatorMap.add("double_array",new DoubleArrayToBytesCreator());
        objectToBytesCreatorMap.add("double_list",new DoubleListToBytesCreator());

        objectToBytesCreatorMap.add("json",new JSONToBytesCreator(objectToBytesCreatorMap));
        objectToBytesCreatorMap.add("json_array",new JSONArrayToBytesCreator(objectToBytesCreatorMap));
        objectToBytesCreatorMap.add("json_list",new JSONListToBytesCreator(objectToBytesCreatorMap));


        bytesToObjectCreatorMap = new BytesToObjectCreatorMap();


        bytesToObjectCreatorMap.add("var_string",new ByteBufferToVariableStringCreator());
        bytesToObjectCreatorMap.add("string",new ByteBufferToStringCreator());
        bytesToObjectCreatorMap.add("hex_string",new ByteBufferToHexStringCreator());
        bytesToObjectCreatorMap.add("var_hex_string",new ByteBufferToVariableHexStringCreator());

        bytesToObjectCreatorMap.add("boolean",new ByteBufferToBooleanCreator());
        bytesToObjectCreatorMap.add("boolean_array",new ByteBufferToBooleanArrayCreator());
        bytesToObjectCreatorMap.add("boolean_list",new ByteBufferToBooleanListCreator());

        bytesToObjectCreatorMap.add("byte",new ByteBufferToByteCreator());
        bytesToObjectCreatorMap.add("byte_array",new ByteBufferToByteArrayCreator());
        bytesToObjectCreatorMap.add("byte_list",new ByteBufferToByteListCreator());

        bytesToObjectCreatorMap.add("short",new ByteBufferToShortCreator());
        bytesToObjectCreatorMap.add("short_array",new ByteBufferToShortArrayCreator());
        bytesToObjectCreatorMap.add("short_list",new ByteBufferToShortListCreator());

        bytesToObjectCreatorMap.add("float",new ByteBufferToFloatCreator());
        bytesToObjectCreatorMap.add("float_array",new ByteBufferToFloatArrayCreator());
        bytesToObjectCreatorMap.add("float_list",new ByteBufferToFloatListCreator());

        bytesToObjectCreatorMap.add("int",new ByteBufferToIntCreator());
        bytesToObjectCreatorMap.add("int_array",new ByteBufferToIntArrayCreator());
        bytesToObjectCreatorMap.add("int_list",new ByteBufferToIntListCreator());

        bytesToObjectCreatorMap.add("double",new ByteBufferToDoubleCreator());
        bytesToObjectCreatorMap.add("double_array",new ByteBufferToDoubleArrayCreator());
        bytesToObjectCreatorMap.add("double_list",new ByteBufferToDoubleListCreator());

        bytesToObjectCreatorMap.add("long",new ByteBufferToLongCreator());
        bytesToObjectCreatorMap.add("long_array",new ByteBufferToLongArrayCreator());
        bytesToObjectCreatorMap.add("long_list",new ByteBufferToLongListCreator());

        bytesToObjectCreatorMap.add("json",new ByteBufferToJSONCreator(bytesToObjectCreatorMap));
        bytesToObjectCreatorMap.add("json_array",new ByteBufferToJSONArrayCreator(bytesToObjectCreatorMap));
        bytesToObjectCreatorMap.add("json_list",new ByteBufferToJSONListCreator(bytesToObjectCreatorMap));
    }

    @Override
    public byte[] encode(JSONObject data, JSONObject scheme) {
        Scheme scheme1 = JSONObject.toJavaObject(scheme,Scheme.class);
        return new JSONToBytes(data,scheme1,objectToBytesCreatorMap).transform();
    }



    @Override
    public JSONObject decode(byte[] data, JSONObject scheme) {
        Scheme scheme1 = JSONObject.toJavaObject(scheme,Scheme.class);
        ByteBuffer buf = ByteBuffer.wrap(data);
        return new BytesToJSON(buf,scheme1,bytesToObjectCreatorMap).transform();
    }

    public static class Field{
        private String name;
        private String type;
        private JSONObject attr;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public JSONObject getAttr() {
            return attr;
        }

        public void setAttr(JSONObject attr) {
            this.attr = attr;
        }
    }

    public static class Scheme{

        private List<Field> fields;

        public List<Field> getFields() {
            return fields;
        }

        public void setFields(List<Field> fields) {
            this.fields = fields;
        }
    }
/*
    @Override
    public byte[] encode(JSONObject data, JSONObject jsonScheme) {

        Scheme scheme = jsonScheme.toJavaObject(Scheme.class);
        List<Field> fieldsSchemes = scheme.getFields();
        int fieldsSize = scheme.getFields().size();
        byte[][] fieldsBytes = new byte[fieldsSize][];
        int resultBytes = 0;
        for (int i = 0; i < fieldsSize; i++){
            Field field = fieldsSchemes.get(i);
            Object fieldValue = data.get(field.getName());
            ObjectToBytesCreator creator = getObjectToBytesTransformCreator(field.getType());
            ObjectToBytesCreatorContext ctx = new ObjectToBytesCreatorContext(scheme,data,fieldsBytes);
            Transform<byte[]> transform = creator.create(ctx);
            byte[] fieldBytes = transform.transform();
            fieldsBytes[i] = fieldBytes;
            resultBytes += fieldBytes.length;
        }

        byte[] result = new byte[resultBytes];

        int resultPos = 0;
        for (int i = 0; i < fieldsSize; i++){
            byte[] field = fieldsBytes[i];
            System.arraycopy(field,0,result,resultPos += field.length,field.length);
        }
        return result;
    }


    @Override
    public JSONObject decode(byte[] data, JSONObject jsonScheme) {
        Scheme scheme = jsonScheme.toJavaObject(Scheme.class);
        List<Field> fields = scheme.getFields();
        int fieldSize = fields.size();
        JSONObject result = new JSONObject();
        for (int i = 0; i < fieldSize; i++){
            Field field = fields.get(i);
            TransformCreator creator = getDecodeCreator(fields.get(i).getType());
            CreatorContext ctx = new BytesToObjectCreatorContext(scheme,data,result);
            Transform transform = null;
            try {
                transform = creator.create(ctx);
                transform.transform();
            }catch (Exception e){
                String msg = String.format("字段%s 解析失败, 错误消息：%s",field.getName(),e.getMessage());
                throw new CodecException(msg);
            }
        }
        return result;
    }

    public void setCreator(String type,ByteBufferToObjectCreator creator){
        this.decodes.put(type.toLowerCase(),creator);
    }

    public void setCreator(String type,ObjectToBytesCreator creator){
        this.encodes.put(type.toLowerCase(),creator);
    }

    private ByteBufferToObjectCreator getDecodeCreator(String type){
        return decodes.get(type.toLowerCase());
    }

    private ObjectToBytesCreator getObjectToBytesTransformCreator(String type){
        return encodes.get(type.toLowerCase());
    }*/


}
